﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using DragonAwakening.Game;

namespace DragonAwakening.Core.World
{
    /// <summary>
    /// World interface.
    /// </summary>
    public interface IWorld
    {
        /// <summary>
        /// Creates the world.
        /// </summary>
        /// <param name="width">Map width.</param>
        /// <param name="height">Map height.</param>
        void CreateWorld(int width, int height);

        /// <summary>
        /// Gets the world size.
        /// </summary>
        Point Size { get; }

        /// <summary>
        /// Gets the map cell.
        /// </summary>
        /// <param name="coordinates">Coordinates of the cell.</param>
        /// <returns>Map cell.</returns>
        MapCell GetCell(Point coordinates);

        /// <summary>
        /// Updates the cell.
        /// </summary>
        /// <param name="cell">New map cell.</param>
        /// <param name="coordinates">Coordinates.</param>
        /// <returns>True if the map cell was set, otherwise false.</returns>
        bool SetCell(MapCell cell, Point coordinates);
    }

    /// <summary>
    /// The world.
    /// </summary>
    public class World : IWorld
    {
        /// <summary>
        /// Initialize the world.
        /// </summary>
        public void CreateWorld(int width, int height)
        {
            this.worldMap = new MapCell[height, width];
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    this.worldMap[y, x] = empty;
                }
            }

            this.size = new Point(width, height);
        }

        /// <summary>
        /// Gets the world size.
        /// </summary>
        public Point Size 
        {
            get { return this.size; } 
        }

        /// <summary>
        /// Gets the map cell.
        /// </summary>
        public MapCell GetCell(Point c)
        { 
            return (0 <= c.X && c.X < this.size.X && 0 <= c.Y && c.Y < this.size.Y) ? this.worldMap[c.Y, c.X] : empty;
        }

        /// <summary>
        /// Updates the cell.
        /// </summary>
        /// <param name="cell">New map cell.</param>
        /// <param name="coordinates">Coordinates.</param>
        /// <returns>True if the map cell was set, otherwise false.</returns>
        public bool SetCell(MapCell cell, Point c)
        { 
            bool isValid = 0 <= c.X && c.X <= this.size.X && 0 <= c.Y && c.Y <= this.size.Y;
            if (isValid)
            {
                this.worldMap[c.Y, c.X] = cell;
            }

            return isValid;
        }

        /// <summary>
        /// The game map.
        /// </summary>
        private MapCell[,] worldMap;

        /// <summary>
        /// Void cell
        /// </summary>
        public static MapCell empty = new MapCell(0, 0, 0, 0, 0, 0, 0, 0);

        /// <summary>
        /// Map size
        /// </summary>
        private Point size = new Point(9, 9);

        /// <summary>
        /// Initializes the world data.
        /// </summary>
        /// <param name="data">Data for the world to be initialized.</param>
        public World()
        {
/*
            var cl_21 = new MapCell(0, 0, 1, 0, 0, 1, 1, 0, new byte[] { 2, 2 });
            var cl_31 = new MapCell(0, 0, 1, 0, 1, 0, 1, 0);
            var cl_22 = new MapCell(0, 0, 0, 1, 0, 1, 1, 0);
            var cl_32 = new MapCell(0, 0, 0, 0, 1, 0, 1, 0);
            var cl_33 = new MapCell(0, 0, 0, 0, 1, 1, 1, 0);
            var cl_14 = new MapCell(0, 0, 1, 0, 0, 1, 1, 0);
            var cl_24 = new MapCell(0, 0, 1, 0, 0, 0, 1, 0);
            var cl_34 = new MapCell(0, 0, 0, 0, 1, 0, 1, 0);
            var cl_15 = new MapCell(0, 0, 0, 0, 0, 1, 1, 0);
            var cl_25 = new MapCell(0, 0, 0, 0, 0, 0, 1, 0);
            var cl_35 = new MapCell(0, 0, 0, 0, 1, 0, 1, 0);
            var cl_16 = new MapCell(0, 0, 0, 1, 0, 1, 1, 0);
            var cl_26 = new MapCell(0, 0, 0, 0, 0, 0, 1, 0, new byte[] { 1 });
            var cl_36 = new MapCell(0, 0, 0, 0, 1, 0, 1, 0);
            var cl_17 = new MapCell(0, 0, 1, 1, 0, 1, 1, 0);
            var cl_27 = new MapCell(0, 0, 0, 1, 0, 0, 1, 0);
            var cl_37 = new MapCell(0, 0, 0, 0, 1, 0, 1, 0);
            var cl_38 = new MapCell(0, 0, 0, 1, 1, 1, 1, 0);

            worldMap = new MapCell[10, 10]
            {    //  0      1      2      3      4      5      6      7      8      9
           / 0 / { empty, empty, empty, empty, empty, empty, empty, empty, empty, empty },
           / 1 / { empty, empty, cl_21, cl_31, empty, empty, empty, empty, empty, empty },
           / 2 / { empty, empty, cl_22, cl_32, empty, empty, empty, empty, empty, empty },
           / 3 / { empty, empty, empty, cl_33, empty, empty, empty, empty, empty, empty },
           / 4 / { empty, cl_14, cl_24, cl_34, empty, empty, empty, empty, empty, empty },
           / 5 / { empty, cl_15, cl_25, cl_35, empty, empty, empty, empty, empty, empty },
           / 6 / { empty, cl_16, cl_26, cl_36, empty, empty, empty, empty, empty, empty },
           / 7 / { empty, cl_17, cl_27, cl_37, empty, empty, empty, empty, empty, empty },
           / 8 / { empty, empty, empty, cl_38, empty, empty, empty, empty, empty, empty },
           / 9 / { empty, empty, empty, empty, empty, empty, empty, empty, empty, empty }
           };
*/
        }
    }

    public static class WorldHelper
    {
        public static Point RotateOffset(Point offset, Sides focus)
        {
            Point result = offset;
            switch (focus)
            {
                case Sides.North: result = new Point(offset.X, -offset.Y); break;
                case Sides.South: result = new Point(-offset.X, offset.Y); break;
                case Sides.West: result = new Point(-offset.Y, -offset.X); break;
                case Sides.East: result = new Point(offset.Y, offset.X); break;
            }

            return result;
        }
    }
}
